<template>
  <div class="img-box">
    <el-upload
      class="avatar-uploader"
      ref="elUpload"
      :disabled="!!value"
      :action="action"
      drag
      :show-file-list="false"
      :http-request="httpRequest"
      :on-success="handleSuccess"
    >
      <div class="preview" v-if="value">
        <el-image :src="value | imgurl" :preview-src-list="[value] | imgurl" class="avatar" />
        <div class="operation" @click.stop>
          <el-button @click="del" type="text" icon="el-icon-delete-solid"></el-button>
          <el-button @click="edit" type="text" icon="el-icon-edit"></el-button>
        </div>
      </div>
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>
    <el-dialog title="裁剪图片" :visible.sync="dialogVisible" width="36%">
      <div class="vue-cropper-box">
        <vue-cropper
          v-if="dialogVisible"
          class="vue-cropper"
          ref="cropper"
          :src="cropUrl"
          :aspectRatio="aspectRatio"
          :minCropBoxWidth="60"
          :minCropBoxHeight="60"
          :minCanvasWidth="100"
          :minCanvasHeight="100"
          :autoCropArea="1"
        ></vue-cropper>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancelCrop">取消</el-button>
        <el-button type="warning" @click="resetCrop">恢复</el-button>
        <el-button type="primary" @click="deterCrop">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { uploadImage } from '@/api/upload'
import VueCropper from 'vue-cropperjs'

export default {
  name: 'upload',
  components: {
    VueCropper,
  },
  props: {
    // 图片上传地址，不做改变
    action: {
      type: String,
      default: '/api/upload/image',
    },
    value: {
      type: String,
      default: '',
    },
    // 是否启用裁剪
    cropper: {
      type: Boolean,
      default: false,
    },
    // 裁剪比例，设置为1限制裁剪为正方形，不填则默认允许长方形
    aspectRatio: {
      type: [Number, undefined],
      default: undefined,
    },
  },
  data() {
    return {
      dialogVisible: false,
      cropUrl: '',
      srcUrl: '',
    }
  },
  methods: {
    httpRequest(option) {
      if (this.cropper) {
        const url = URL.createObjectURL(option.file)
        this.srcUrl = url
        this.enable(url)
      } else {
        this.upload(option.file)
      }
    },
    enable(url) {
      this.cropUrl = url
      this.dialogVisible = true
    },
    async upload(file) {
      const fd = new FormData()
      fd.append('file', file)
      const data = await uploadImage(fd)
      if (data.code !== 200) return this.$emit('load-error', data)
      this.$emit('input', data.files[0].name)
    },
    cancelCrop() {
      this.$refs.elUpload.clearFiles()
      this.$refs.cropper.reset()
      this.dialogVisible = false
    },
    deterCrop() {
      this.dialogVisible = false
      const cvs = this.$refs.cropper.getCroppedCanvas()
      this.$refs.cropper.reset()
      cvs.toBlob((blob) => {
        this.upload(blob)
      })
    },
    resetCrop() {
      this.$refs.cropper.reset()
    },
    handleSuccess(req) {
      if (!req) return
      if (!req.files[0]) return
      this.$emit('input', req.files[0].name)
      this.$emit('change', req.files[0].name)
    },
    del() {
      this.$emit('input', '')
      this.$emit('change', '')
    },
    edit() {
      this.enable(this.srcUrl || '/image/' + this.value)
    },
  },
}
</script>

<style lang="scss" scoped>
.img-box {
  width: 180px;
  // height: 180px;
  .avatar-uploader,
  .preview {
    width: 100%;
    height: 100%;
    .operation {
      display: flex;
      background-color: rgba($color: #333, $alpha: 0.4);
      opacity: 0;
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      z-index: 5;
      transition: opacity 0.2s;
      align-items: center;
      justify-content: center;
      .el-button {
        width: 36px;
        color: #fff;
        &:hover {
          background-color: rgba($color: #333, $alpha: 0.5);
        }
      }
    }
    &:hover {
      .operation {
        opacity: 1;
      }
    }
  }
}
::v-deep {
  .el-upload--text {
    width: 100%;
    height: 100%;
  }
  .el-upload-dragger {
    width: 100%;
    height: 100%;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .el-dialog {
    min-width: 400px;
  }
}
.vue-cropper-box {
  width: 360px;
  height: 360px;
  margin: auto;
  .vue-cropper {
    width: 100%;
    height: 100%;
  }
}
.avatar-uploader .el-upload {
  // border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
}
.avatar {
  width: 100%;
  height: 100%;
  display: block;
}
</style>
